package com.plm.k8s.myk8sapi.cmd.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.plm.k8s.myk8sapi.cmd.AbstractLocalCmd;
import com.plm.k8s.myk8sapi.cmd.IPodCmd;
import com.plm.k8s.myk8sapi.pojo.entity.pod.*;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.*;

/**
 * @author 潘磊明
 * 版本号：1.0
 * 创建日期：2021/7/20 8:40
 */
@Service
public class PodCmdImpl extends AbstractLocalCmd implements IPodCmd {

    @Override
    public List<PodEntity> listPods() throws Exception {
        return listPods(true, null, null, null);
    }

    @Override
    public List<PodEntity> listPods(boolean isAll, String namespace, String nameFilter, Map<String, String> labelFilter) throws Exception {
        String cmd = generateListPodsCmd(isAll, namespace, nameFilter, labelFilter);
        ApiPodEntity apiPodEntity = execForYamlObject(cmd, ApiPodEntity.class);
        if (apiPodEntity == null) return Collections.emptyList();
        return apiPodEntity.getItems();
    }

    @Override
    public boolean createPod(File yamlFile) throws Exception {
        String result = applyYamlFile(yamlFile);
        if (!result.contains("created")) {
            throw new Exception(result);
        }
        return true;
    }

    @Override
    public boolean createPodDetail(PodEntity podEntity) throws Exception {
        if (podEntity == null) throw new Exception("pod信息不能为空");
        File file = transferObject2YamlFile(podEntity);
        return createPod(file);
    }

    /**
     * 向容器添加更多信息
     * @param podName
     * @param image
     * @param podEntity
     * @param envs
     * @param ports
     * @param volumeMounts
     * @param volumes
     * @param namespace
     * @param terminationGracePeriodSeconds
     * @param command
     * @param startupProbe
     * @param livenessProbe
     * @param readinessProbe
     * @param lifecycle
     */
    private void setMorePodInfo(String podName, String image, String imagePullPolicy, PodEntity podEntity, List<PodSpecContainerEnvEntity> envs,
            List<PodSpecContainerPortEntity> ports, List<PodSpecContainerVolumeMountEntity> volumeMounts,
            List<PodSpecVolumeEntity> volumes, String namespace, Integer terminationGracePeriodSeconds,
            List<String> command, PodSpecContainerStartupProbeEntity startupProbe,
            PodSpecContainerLivenessProbeEntity livenessProbe, PodSpecContainerReadinessProbeEntity readinessProbe,
            PodSpecContainerLifecycleEntity lifecycle, PodSpecContainerResourcesRequestsEntity requests,
            PodSpecContainerResourcesLimitsEntity limits) {
        PodMetadataEntity metadataEntity = podEntity.getMetadata();
        if (StringUtils.hasText(namespace)) metadataEntity.setNamespace(namespace);
        PodSpecEntity specEntity = podEntity.getSpec();
        PodSpecContainerEntity containerEntity = setContainerInfo(podName, image, imagePullPolicy, envs, ports, volumeMounts, command,
                startupProbe, livenessProbe, readinessProbe, lifecycle, requests, limits);
        List<PodSpecContainerEntity> containers = specEntity.getContainers();
        if (CollectionUtil.isNotEmpty(containers)) containers.add(containerEntity);
        else specEntity.setContainers(Arrays.asList(containerEntity));
        if (CollectionUtil.isNotEmpty(volumes)) specEntity.setVolumes(volumes);
        if (terminationGracePeriodSeconds != null) specEntity.setTerminationGracePeriodSeconds(terminationGracePeriodSeconds);
    }

    @Override
    public boolean deletePod(String podName, String namespace) throws Exception {
        if (!StringUtils.hasText(podName)) throw new Exception("pod名称不能为空");
        String cmd = generateDeletePodCmd(podName, namespace);
        String result = exec(cmd);
        if (!(String.format("pod \"%s\" deleted", podName).equals(trimBr(result)))) {
            throw new Exception(result);
        }
        return true;
    }

    @Override
    public void deletePods(List<String> podsNames, String namespace) throws Exception {
        if (CollectionUtil.isEmpty(podsNames)) throw new Exception("pod名称列表不能为空");
        String cmd = generateDeletePodsCmd(podsNames, namespace);
        exec(cmd);
    }

    private String generateDeletePodsCmd(List<String> podsNames, String namespace) {
        StringBuilder sb = new StringBuilder(generateKubeCmdBase());
        sb.append("delete pods ");
        for (String name : podsNames) {
            sb.append(name).append(CMD_DELIMITER);
        }
        addNamespace(sb, namespace);
        return sb.toString();
    }

    @Override
    public List<PodTopEntity> topPods(String podName, String namespace, Map<String, String> labels, String sortBy, boolean isAll) throws Exception {
        String cmd = generateTopPodsCmd(podName, namespace, labels, sortBy, isAll);
        List<String> list = execForLine(cmd);
        List<PodTopEntity> podTopList = parsePodTopResult(namespace, list);
        return podTopList;
    }

    private List<PodTopEntity> parsePodTopResult(String namespace, List<String> list) throws Exception {
        if (CollectionUtil.isEmpty(list)) return Collections.emptyList();
        String head = list.get(0);
        if (!head.startsWith("NAME")) throw new Exception(StringUtils.collectionToDelimitedString(list, " "));
        List<PodTopEntity> data = new LinkedList<>();
        int tmp = 1;
        if (head.startsWith("NAMESPACE")) tmp = 0;
        for (int i = 1; i < list.size(); i++) {
            String str = list.get(i);
            String[] array = str.split("\\s+");
            PodTopEntity entity = new PodTopEntity();
            if (tmp == 0) entity.setNamespace(array[0]);
            else entity.setNamespace(namespace);
            entity.setName(array[1 - tmp]);
            entity.setCpu(array[2 - tmp]);
            entity.setMemory(array[3 - tmp]);
            data.add(entity);
        }
        return data;
    }

    private String generateTopPodsCmd(String podName, String namespace, Map<String, String> labels, String sortBy, boolean isAll) {
        StringBuilder sb = new StringBuilder(generateKubeCmdBase());
        sb.append("top pods ");
        if (isAll) sb.append(" -A");
        else {
            if (StringUtils.hasText(podName)) sb.append(CMD_DELIMITER).append(podName);
            if (StringUtils.hasText(sortBy)) sb.append(CMD_DELIMITER).append("--sort-by=").append(sortBy);
            if (StringUtils.hasText(namespace)) sb.append(CMD_DELIMITER).append("-n ").append(namespace);
            if (CollectionUtil.isNotEmpty(labels)) addLabelFilter(sb, labels);
        }
        sb.append(" --use-protocol-buffers");
        return sb.toString();
    }

    /**
     * 生成删除pod的命令
     * @param podName
     * @param namespace
     * @return
     */
    private String generateDeletePodCmd(String podName, String namespace) {
        StringBuilder sb = new StringBuilder(generateKubeCmdBase());
        sb.append("delete pods ").append(podName);
        if (StringUtils.hasText(namespace)) sb.append(" -n ").append(namespace);
        return sb.toString();
    }

    /**
     * 设置单个容器信息
     * @param podName
     * @param imageName
     * @param ports
     * @param volumeMounts
     * @return
     */
    private PodSpecContainerEntity setContainerInfo(String podName, String imageName, String imagePullPolicy,
            List<PodSpecContainerEnvEntity> envs, List<PodSpecContainerPortEntity> ports, List<PodSpecContainerVolumeMountEntity> volumeMounts,
            List<String> command, PodSpecContainerStartupProbeEntity startupProbe, PodSpecContainerLivenessProbeEntity livenessProbe,
            PodSpecContainerReadinessProbeEntity readinessProbe, PodSpecContainerLifecycleEntity lifecycle,
            PodSpecContainerResourcesRequestsEntity requests, PodSpecContainerResourcesLimitsEntity limits) {
        PodSpecContainerEntity containerEntity = new PodSpecContainerEntity();
        containerEntity.setImage(imageName);
        containerEntity.setName(podName);
        if (StringUtils.hasText(imagePullPolicy)) containerEntity.setImagePullPolicy(imagePullPolicy);
        if (CollectionUtil.isNotEmpty(command)) containerEntity.setCommand(command);
        if (!CollectionUtil.isEmpty(envs)) containerEntity.setEnv(envs);
        if (!CollectionUtil.isEmpty(ports)) containerEntity.setPorts(ports);
        if (CollectionUtil.isNotEmpty(volumeMounts)) containerEntity.setVolumeMounts(volumeMounts);
        if (startupProbe != null) containerEntity.setStartupProbe(startupProbe);
        if (livenessProbe != null) containerEntity.setLivenessProbe(livenessProbe);
        if (readinessProbe != null) containerEntity.setReadinessProbe(readinessProbe);
        if (lifecycle != null) containerEntity.setLifecycle(lifecycle);
        PodSpecContainerResourcesEntity resourcesEntity = new PodSpecContainerResourcesEntity();
        if (requests != null) resourcesEntity.setRequests(requests);
        if (limits != null) resourcesEntity.setLimits(limits);
        containerEntity.setResources(resourcesEntity);
        return containerEntity;
    }

    private String generateListPodsCmd(boolean isAll, String namespace, String nameFilter, Map<String, String> labelFilter) {
        StringBuilder sb = new StringBuilder(generateKubeCmdBase());
        sb.append("get pods -o yaml");
        if(isAll) {
            sb.append(" -A");
        } else {
            if (StringUtils.hasText(namespace)) sb.append(String.format(" -n %s", namespace));
        }
        if (StringUtils.hasText(nameFilter)) addNameFilter(sb, nameFilter);
        if (!CollectionUtil.isEmpty(labelFilter)) addLabelFilter(sb, labelFilter);
        return sb.toString();
    }
}
